package com.chenwc.wso2;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.chenwc.enumeration.LocaleLanguage;
import com.chenwc.enumeration.TranslateSoftware;
import com.chenwc.util.JarFileSignEntity;
import com.chenwc.util.TranslatePropertiesFile;
import com.chenwc.util.Util;
import com.chenwc.util.fileutil.WriteFile;
import com.chenwc.util.fileutil.jarfile.Decompression;
import com.chenwc.util.fileutil.propertiesfile.PropertiesFileUtil;
import com.chenwc.util.multithread.MultiStepJob;
import com.chenwc.util.multithread.SessionReferenceThreadAsync;
import com.chenwc.util.multithread.TranslateJarPropertiesFileMultiStep;
import com.chenwc.util.multithread.TranslatePropertiesFileMultiStep;
import com.chenwc.util.threadpool.NameTreadFactory;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 多线程翻译
 * @author chenwc
 * @package com.chenwc.wso2
 * @project wso2-sinicization
 * @date 2024/5/26
 */
public class TranslateWso2MutilThread {

    private static final Logger log = LoggerFactory.getLogger(TranslateWso2MutilThread.class);

    /**
     * 阻塞队列
     */
    private static BlockingQueue<MultiStepJob> QUEUE = new LinkedBlockingQueue<>();

    //线程池实例
    private static ExecutorService executorService = new ThreadPoolExecutor(20, 100,
            10, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(50), new NameTreadFactory());
    public static void main(String[] args) {
        String wso2FilePath = "F:\\wso2is-7.0.0";
        String jarPluginPath = "repository\\components\\plugins";
        String outputPath = "F:\\wso2汉化\\wso2is-7.0.0";
        //翻译plugins目录里面所有ui.jar文件里面的Resources.properties文件
        //翻译后的jar包输出到outputPath下面的jar目录，解压后的jar包在outputPath下面的file目录
//        translateAllJarPropertiesFile(wso2FilePath + "\\" + jarPluginPath,
//                outputPath,
//                TranslateSoftware.BAIDU,
//                LocaleLanguage.CHINA,
//                5);

        //翻译所有非jar包里面的Resources.properties文件，文件路径要包含Resources和i18n
        //翻译后的文件直接输出到原目录，新文件名为：Resources_zh_CN.properties
        translateAllPropertiesFile(wso2FilePath,
                TranslateSoftware.BAIDU,
                LocaleLanguage.CHINA,
                2);
    }

    /**
     * 翻译jar包里面的properties文件
     *
     * @param wso2FilePath      wso2文件路径
     * @param outputPath        翻译输出文件路径
     * @param translateSoftware 翻译软件
     * @param localeLanguage    国际化语言
     * @param threadCount       线程数
     */
    public static void translateAllJarPropertiesFile(String wso2FilePath,
                                                     String outputPath,
                                                     TranslateSoftware translateSoftware,
                                                     LocaleLanguage localeLanguage,
                                                     int threadCount) {
        List<String> filelist = Util.searchUiFileList(wso2FilePath);
        String logFilePath = "info.log";
        File logFile = new File(outputPath + File.separator + logFilePath);
        log.info("logFile: {}", logFile.getAbsolutePath());
        List<JarFileSignEntity> jarFileSignEntityList = new ArrayList<>();
        try {
            if (logFile.exists()) {
                WriteFile.write(logFile, null);
            } else {
                FileUtils.touch(logFile);
            }
            //获取所有需要翻译的properties文件
            for (String file : filelist) {
                //需要解压的文件
                File jarFile = new File(file);
                JarFileSignEntity jarFileSign = new JarFileSignEntity();
                jarFileSign.setJarPath(file);
                String originalUrl = jarFile.getName().replace(".jar", "");
                jarFileSign.setOriginalUrl(originalUrl);
                String filePath = outputPath + "\\file\\" + originalUrl;
                jarFileSign.setFilePath(filePath);
                String newFilePath = outputPath + "\\jar\\" + jarFile.getName();
                jarFileSign.setJarNewPath(newFilePath);

                log.debug("JarFileSignEntity: {}", JSON.toJSONString(jarFileSign, JSONWriter.Feature.WriteMapNullValue));
                //解压后文件的输出目录
                File targetDir = new File(filePath);
                if (targetDir.isDirectory()) {
                    FileUtils.deleteDirectory(targetDir);
                } else {
                    FileUtils.deleteQuietly(targetDir);
                }
                Decompression.uncompress(jarFile, targetDir);
                List<String> list = Util.searchResourcesPropertiesFileList(filePath);
                jarFileSign.setResourcePropertiesFileList(list);
                jarFileSignEntityList.add(jarFileSign);
            }
            log.debug("jarFileSignEntityList: {}", JSON.toJSONString(jarFileSignEntityList, JSONWriter.Feature.WriteMapNullValue));
            log.info("开始翻译");
            QUEUE = new LinkedBlockingQueue<>();
            //遍历所有jar文件
            for (JarFileSignEntity jarFileSignEntity : jarFileSignEntityList) {
                QUEUE.add(new TranslateJarPropertiesFileMultiStep(1, jarFileSignEntity, logFile, localeLanguage, translateSoftware));
            }
        } catch (IOException e) {
            log.error("Error occurred: ", e);
        }
        if (executorService.isShutdown()){
            executorService = new ThreadPoolExecutor(20, 100,
                    10, TimeUnit.SECONDS,
                    new ArrayBlockingQueue<>(50), new NameTreadFactory());
        }
        log.info(">>> Start");
        //开线程
        CountDownLatch doneSignal = new CountDownLatch(threadCount);
        //这里开了threadCount个线程，每个线程都会从阻塞队列中取任务执行，当阻塞队列中没有任务时，线程会结束
        for (int i = 0; i < threadCount; i++) {
            //异步执行
            SessionReferenceThreadAsync.GetResultCompletableFuture completableFuture =
                    new SessionReferenceThreadAsync.GetResultCompletableFuture(doneSignal, QUEUE);
            CompletableFuture.supplyAsync(completableFuture, executorService)
                    .whenComplete((res, ex) -> {
                        if (ex != null) {
                            log.error(">>> 当前线程：" + Thread.currentThread().getName() + ">>> 异常：", ex);
                        }
                        else {
                            log.info(">>> 当前线程：" + Thread.currentThread().getName() + "执行成功！");
                        }
                    });
        }
        executorService.shutdown();
        log.info(">>> Wait ... ");
        try {
            doneSignal.await();
        } catch (InterruptedException ie) {
            //just leave
        }
        log.info(">>> Done");
    }


    /**
     * 翻译所有i18n的Resources.properties文件
     *
     * @param wso2FilePath      wso2文件路径
     * @param translateSoftware 翻译软件
     * @param localeLanguage    国际化语言
     * @param threadCount       线程数
     */
    public static void translateAllPropertiesFile(String wso2FilePath,
                                                  TranslateSoftware translateSoftware,
                                                  LocaleLanguage localeLanguage,
                                                  int threadCount) {

        List<String> resourcePropertiesFileList = Util.searchResourcesPropertiesFileList(wso2FilePath);
        resourcePropertiesFileList = resourcePropertiesFileList.stream().filter(s -> "Resources.properties".equals(new File(s).getName())).collect(Collectors.toList());
        QUEUE = new LinkedBlockingQueue<>();
        for (String resourcePropertiesFile : resourcePropertiesFileList) {
            QUEUE.add(new TranslatePropertiesFileMultiStep(1, resourcePropertiesFile, localeLanguage, translateSoftware));
        }
        if (executorService.isShutdown()){
            executorService = new ThreadPoolExecutor(20, 100,
                    10, TimeUnit.SECONDS,
                    new ArrayBlockingQueue<>(50), new NameTreadFactory());
        }
        log.info(">>> Start");
        //开线程
        CountDownLatch doneSignal = new CountDownLatch(threadCount);
        //这里开了threadCount个线程，每个线程都会从阻塞队列中取任务执行，当阻塞队列中没有任务时，线程会结束
        for (int i = 0; i < threadCount; i++) {
            //异步执行
            SessionReferenceThreadAsync.GetResultCompletableFuture completableFuture =
                    new SessionReferenceThreadAsync.GetResultCompletableFuture(doneSignal, QUEUE);
            CompletableFuture.supplyAsync(completableFuture, executorService)
                    .whenComplete((res, ex) -> {
                        if (ex != null) {
                            log.error(">>> 当前线程：" + Thread.currentThread().getName() + ">>> 异常：", ex);
                        }
                        else {
                            log.info(">>> 当前线程：" + Thread.currentThread().getName() + "执行成功！");
                        }
                    });
        }
        executorService.shutdown();
        log.info(">>> Wait ... ");
        try {
            doneSignal.await();
        } catch (InterruptedException ie) {
            //just leave
        }
        log.info(">>> Done");
    }
}
